#pragma once
#include "Socket.hpp"
#include <sys/select.h>
#include <sys/time.h>
#include <iostream>
using namespace std;

static const uint16_t default_port = 8080;
// static string default_ip = "0.0.0.0";
static const int fd_max = (sizeof(fd_set) * 8);
static const int default_fd = -1;
class Server
{
public:
    Server(uint16_t port = default_port) : _port(port)
    {
        for (int i = 0; i < fd_max; i++)
        {
            fd_array[i] = -1;
        }
    }
    ~Server()
    {
        close(_listenSock.Fd());
    }
    bool Init()
    {
        _listenSock.Socket();
        _listenSock.Bind(_port);
        _listenSock.Listen();
        return true;
    }
    void Start()
    {
        int listenSock = _listenSock.Fd();
        fd_array[0] = listenSock;
        while (true)
        {
            fd_set rfds;
            FD_ZERO(&rfds);
            int max_fd = fd_array[0];
            for (int i = 0; i < fd_max; i++)
            {
                if (fd_array[i] == default_fd)
                {
                    continue;
                }
                FD_SET(fd_array[i], &rfds);
                if (fd_array[i] > max_fd)
                {
                    max_fd = fd_array[i];
                    //lg(Info, "max_fd update: sock fd: %d", max_fd);
                }
            }
            struct timeval timeout = {1, 0};
            // 这里不能用connect
            //  string client_ip;
            //  uint16_t client_port;
            //  int n = _listenSock.Accept(&client_ip, &client_port);
            int n = select(max_fd + 1, &rfds, nullptr, nullptr, &timeout);
            switch (n)
            {
            case 0:
                cout << "time out, time: " << timeout.tv_sec << "." << timeout.tv_usec << endl;
                break;
            case -1:
                cerr << "select error" << endl;
                break;
            default:
                cout << "get new link..." << endl;
                Dispatcher(rfds);
                break;
            }
        }
    }
    void Dispatcher(fd_set &rfds)
    {
        for (int i = 0; i < fd_max; i++)
        {
            int fd = fd_array[i];
            if (fd == default_fd)
            {
                continue;
            }
            if (FD_ISSET(fd, &rfds))
            {
                if(fd == _listenSock.Fd())
                {
                     // 有新连接到来
                    lg(Debug, "listen事件就绪");
                    Accepter();
                }
                else 
                {
                    // 读事件就绪
                    lg(Debug, "读事件就绪");
                    Recver(fd_array[i], i);
                }
               
            }
            
        }
    }
    void Accepter()
    {
        // 1.获起新连接
        string client_ip;
        uint16_t client_port = 0;
        int sock = _listenSock.Accept(&client_ip, &client_port);
        if (sock < 0)
        {
            return;
        }
        lg(Info, "Accept success: client ip : %s, client port: %d", client_ip.c_str(), client_port);
        // 2.将文件描述符添加进辅助数组
        int pos = 0;
        for (; pos < fd_max; pos++)
        {
            if (fd_array[pos] != default_fd)
                continue;
            else
                break;
        }
        if (pos == fd_max)
        {
            lg(Warning, "server is full");
            close(sock);
        }
        else
        {
            fd_array[pos] = sock;
            lg(Info, "pos: %d", pos);
            SockDebug();
        }
    }
    void Recver(int fd, int pos)
    {
        char buffer[1024];
        int n = read(fd, buffer, sizeof(buffer) - 1);
        if (n > 0)
        {
            buffer[n] = 0;
            cout << "get a message: " << buffer << endl;
        }
        else if (n == 0)
        {
            close(fd);
            fd_array[pos] = default_fd;
            lg(Info, "sever close, me too! fd: %d", fd);
        }
        else
        {
            close(fd);
            fd_array[pos] = default_fd;
            lg(Info, "read error, fd: %d", fd);
        }
    }
    void SockDebug()
    {
        cout << "sock list: ";
        for (int i = 0; i < fd_max; i++)
        {
            if (fd_array[i] == default_fd)
                continue;
            cout << fd_array[i];
        }
        cout << endl;
    }

private:
    Sock _listenSock;
    uint16_t _port;
    int fd_array[fd_max];
};